﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Graph = System.Windows.Forms.DataVisualization.Charting;
using System.Drawing;

namespace SignLockerTest
{
    public class SignChart : Graph.Chart
    {
        private Color[] _lineColor = new Color[] { Color.Red, Color.LightGreen, Color.LightBlue, Color.GreenYellow };

        public double MinX
        {
            get { return ChartAreas[0].AxisX.Minimum; }
            set { ChartAreas[0].AxisX.Minimum = value; }
        }

        public double MaxX 
        {
            get { return ChartAreas[0].AxisX.Maximum; }
            set { ChartAreas[0].AxisX.Maximum = value; }
        }

        public double MinY
        {
            get { return ChartAreas[0].AxisY.Minimum; }
            set { ChartAreas[0].AxisY.Minimum = value; }
        }

        public double MaxY
        {
            get { return ChartAreas[0].AxisY.Maximum; }
            set { ChartAreas[0].AxisY.Maximum = value; }
        }

        /// <summary>
        /// Khởi tạo đối tượng đồ thị
        /// Chú ý: chưa gán Control chứa đồ thị
        /// </summary>
        public SignChart()
            : base() 
        {
            Initialize();
        }

        /// <summary>
        /// Khởi tạo đối tượng đồ thị
        /// </summary>
        /// <param name="parent">Control chứa đồ thị</param>
        public SignChart(System.Windows.Forms.Control parent)
            : base()
        {
            Initialize();
            parent.Controls.Add(this);
            this.Dock = System.Windows.Forms.DockStyle.Fill;
        }

        private void Initialize()
        {
            this.ChartAreas.Add("draw");
            this.ChartAreas["draw"].AxisX.Minimum = 0;
            this.ChartAreas["draw"].AxisX.Maximum = 1000;
            this.ChartAreas["draw"].AxisX.Interval = 100;
            this.ChartAreas["draw"].AxisX.MajorGrid.LineColor = Color.White;
            this.ChartAreas["draw"].AxisX.MajorGrid.LineDashStyle = Graph.ChartDashStyle.Dash;
            this.ChartAreas["draw"].AxisY.Minimum = 0;
            this.ChartAreas["draw"].AxisY.Maximum = 0.4;
            this.ChartAreas["draw"].AxisY.Interval = 0.5;
            this.ChartAreas["draw"].AxisY.MajorGrid.LineColor = Color.White;
            this.ChartAreas["draw"].AxisY.MajorGrid.LineDashStyle = Graph.ChartDashStyle.Dash;

            this.ChartAreas["draw"].BackColor = Color.Black;
        }

        /// <summary>
        /// Vẽ đồ thị
        /// </summary>
        /// <param name="name">Tên đồ thị</param>
        /// <param name="legendText">Tiêu đề</param>
        /// <param name="points">Tọa độ các điểm (x, y)</param>
        public void DrawSeries(string name, string legendText, DataPoint[] points)
        {
            int minX = (int)Math.Floor(points.Min((x) => x.XValue));
            int minY = (int)Math.Floor(points.Min((y) => y.YValue));
            if (minX < MinX) MinX = minX;
            if (minY < MinY) MinY = minY;

            int maxX = (int)Math.Ceiling(points.Max((x) => x.XValue));
            int maxY = (int)Math.Ceiling(points.Max((y) => y.YValue));
            if (maxX > MaxX) MaxX = maxX;
            if (maxY > MaxY) MaxY = maxY;

            Graph.Series series = new Graph.Series(name)
            {
                ChartType = Graph.SeriesChartType.Line,
                Color = _lineColor[Series.Count % _lineColor.Length],
                LegendText = legendText,
                BorderWidth = 3
            };

            for (int i = 0; i < points.Length; i++)
            {
                series.Points.AddXY(points[i].XValue, points[i].YValue);
            }
            Legends.Add(legendText);
            Legends[legendText].BorderColor = _lineColor[Series.Count % _lineColor.Length];
            this.Series.Add(series);
        }

        /// <summary>
        /// Di chuyển đồ thị theo các hướng
        /// </summary>
        /// <param name="seriesName">Tên đồ thị</param>
        /// <param name="direction">Hướng di chuyển</param>
        /// <param name="step">Khoảng cách di chuyển</param>
        public void Move(string seriesName, Direction direction, double step)
        {
            if (step == 0) return;

            Graph.DataPoint[] points = Series[seriesName].Points.ToArray();

            foreach (Graph.DataPoint p in points)
            {
                switch (direction)
                {
                    case Direction.Up:
                        for (int i = 0; i < p.YValues.Length; i++)
                            p.YValues[i] += step;
                        break;
                    case Direction.Down:
                        for (int i = 0; i < p.YValues.Length; i++)
                            p.YValues[i] -= step;
                        break;
                    case Direction.Left:
                        p.XValue -= step;
                        break;
                    case Direction.Right:
                        p.XValue += step;
                        break;

                }
            }

            Series[seriesName].Points.Clear();
            for (int i = 0; i < points.Length; i++)
            {
                Series[seriesName].Points.Add(points[i]);
            }

            int minX = (int)Math.Floor(points.Min((x) => x.XValue));
            int minY = (int)Math.Floor(points.Min((y) => y.YValues.Min()));
            if (minX < MinX) MinX = minX;
            if (minY < MinY) MinY = minY;

            int maxX = (int)Math.Ceiling(points.Max((x) => x.XValue));
            int maxY = (int)Math.Ceiling(points.Max((y) => y.YValues.Max()));
            if (maxX > MaxX) MaxX = maxX;
            if (maxY > MaxY) MaxY = maxY;
        }
    }

    public class DataPoint
    {
        public double XValue { get; set; }
        public double YValue { get; set; }

        public DataPoint() { }

        public DataPoint(double x, double y)
        {
            XValue = x;
            YValue = y;
        }
    }

    public enum Direction
    {
        Up, Down, Left, Right
    }
}
